package com.hsjk.szwj.module.pay.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hsjk.szwj.framework.common.exception.ServiceException;
import com.hsjk.szwj.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.hsjk.szwj.framework.security.core.LoginUser;
import com.hsjk.szwj.framework.security.core.util.SecurityFrameworkUtils;
import com.hsjk.szwj.module.member.api.user.MemberUserApi;
import com.hsjk.szwj.module.member.api.user.dto.MemberUserRespDTO;
import com.hsjk.szwj.module.pay.constant.PayOrderConstant;
import com.hsjk.szwj.module.pay.constant.PayWayCodeConstant;
import com.hsjk.szwj.module.pay.controller.AbstractPayOrderController;
import com.hsjk.szwj.module.pay.controller.app.order.vo.UnifiedOrderReqVO;
import com.hsjk.szwj.module.pay.controller.app.order.vo.UnifiedOrderRespVO;
import com.hsjk.szwj.module.pay.dal.dataobject.CommonPayResult;
import com.hsjk.szwj.module.pay.dal.dataobject.order.PayOrderDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.MchAppDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.MchInfoDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.MchPayPassageDO;
import com.hsjk.szwj.module.pay.dal.dataobject.system.PayWayDO;
import com.hsjk.szwj.module.pay.dal.mysql.IMchPayPassageMapper;
import com.hsjk.szwj.module.pay.dal.mysql.IPayOrderMapper;
import com.hsjk.szwj.module.pay.enums.IfCodeEnum;
import com.hsjk.szwj.module.train.api.IOrderApi;
import com.hsjk.szwj.module.train.api.dto.OrderDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author chenjiawei
 * @desc
 * @Date 2023/08/28 21:18
 **/
@Service
@Slf4j
public class PayServiceImpl extends AbstractPayOrderController implements IPayService {
    @Resource
    private IOrderApi orderApi;
    @Resource
    private PayWayService payWayService;
    @Resource
    private MemberUserApi memberUserApi;
    @Resource
    private IMchInfoService mchInfoService;
    @Resource
    private IMchAppService mchAppService;
    @Resource
    private ConfigContextQueryService configContextQueryService;
    @Value("${szwj.pay.base-url}")
    private String payBaseUrl;

    @Resource
    private IMchPayPassageMapper mchPayPassageMapper;

    @Resource
    private IPayOrderMapper payOrderMapper;


    @Override
    public CommonPayResult unifiedPay(Long orderId, String wayCode) {
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        MemberUserRespDTO memberInfo = memberUserApi.getUser(user.getId());
        log.info("memberInfo:{}", memberInfo);
        MchInfoDO mchInfoDO = mchInfoService.getMchInfoByTenant();
        OrderDTO orderDTO = orderApi.getOrderInfoById(orderId);
        MchPayPassageDO mchPayPassageDO = mchPayPassageMapper
                .selectOne(new LambdaQueryWrapper<MchPayPassageDO>()
                        .eq(MchPayPassageDO::getWayCode, wayCode)
                        .eq(MchPayPassageDO::getMchId, mchInfoDO.getId()));
        MchAppDO mchAppDO = mchAppService.getById(mchPayPassageDO.getAppId());
        //获取参数 & 验签
        UnifiedOrderReqVO rq = new UnifiedOrderReqVO();
        rq.setMchOrderId(Long.valueOf(orderDTO.getOrderNo()));
        rq.setAmount(orderDTO.getOrderPrice() * orderDTO.getAmount());
        rq.setWayCode(wayCode);
        rq.setCurrency("CNY");
        rq.setClientIp("192.166.1.132");
        rq.setSubject("商品标题");
        rq.setBody("商品描述");
        Long payOrderId = IdUtil.getSnowflakeNextId();
        rq.setPayOrderId(payOrderId);
        String notifyUrl = payBaseUrl + "/app-api/pay/callback/" + IfCodeEnum.WXPAY.getCode() + "/" + payOrderId;
        rq.setNotifyUrl(notifyUrl);
        String returnUrl = payBaseUrl + "/app-api/pay/callback/return/" + IfCodeEnum.WXPAY.getCode();
        rq.setReturnUrl(returnUrl);
        if (ObjectUtil.isNotNull(memberInfo)) {
            if (PayWayCodeConstant.WX_JSAPI.equals(wayCode)) {
                rq.setChannelExtra(channelExtra(wayCode, memberInfo.getOpenId()));
            } else if (PayWayCodeConstant.WX_LITE.equals(wayCode)) {
                rq.setChannelExtra(channelExtra(wayCode, memberInfo.getWxLiteOpenId()));
            }
        }
        rq.setExtParam("");
        if (ObjectUtil.isNotNull(mchAppDO)) {
            rq.setAppId(mchAppDO.getId());
        }
        if (ObjectUtil.isNotNull(mchInfoDO)) {
            rq.setMchId(mchInfoDO.getId());
        }
        UnifiedOrderReqVO bizRQ = buildBizRQ(rq);
        log.info("bizRQ:{}", bizRQ);
        CommonPayResult commonPayResult = unifiedOrder(wayCode, bizRQ);
        if (commonPayResult.getData() == null) {
            return commonPayResult;
        }
        UnifiedOrderRespVO bizRes = (UnifiedOrderRespVO) commonPayResult.getData();
        //聚合接口，返回的参数
        UnifiedOrderRespVO res = new UnifiedOrderRespVO();
        BeanUtils.copyProperties(bizRes, res);

        //只有 订单生成（QR_CASHIER） || 支付中 || 支付成功返回该数据
        if (bizRes.getOrderState() != null && (bizRes.getOrderState()
                == PayOrderConstant.STATE_INIT || bizRes.getOrderState()
                == PayOrderConstant.STATE_ING || bizRes.getOrderState()
                == PayOrderConstant.STATE_SUCCESS)) {
            res.setPayDataType(bizRes.buildPayDataType());
            res.setPayData(bizRes.buildPayData());
        }
        return CommonPayResult.okWithSign(res,
                configContextQueryService.queryMchApp(rq.getMchId(), rq.getAppId()).getAppSecret());
    }

    @Override
    public PayOrderDO getPayOrderById(Long id) {
        return payOrderMapper.selectById(id);
    }

    String channelExtra(String wayCode, String openId) {
        if ("WX_LITE".equals(wayCode)) {
            return wxJsapiExtra(openId);
        }
        if ("WX_JSAPI".equals(wayCode)) {
            return wxJsapiExtra(openId);
        }
        return "";
    }

    private String wxJsapiExtra(String openId) {
        JSONObject obj = new JSONObject();
        obj.putIfAbsent("openId", openId);
        return obj.toString();
    }

    private UnifiedOrderReqVO buildBizRQ(UnifiedOrderReqVO rq) {

        //支付方式  比如： ali_bar
        String wayCode = rq.getWayCode();

        if (payWayService.count(new LambdaQueryWrapper<PayWayDO>()
                .eq(PayWayDO::getWayCode, wayCode)) <= 0) {
            throw new ServiceException(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
                    "不支持的支付方式");
        }

        //转换为 bizRQ
        return rq.buildBizRQ();
    }
}
